home *** CD-ROM | disk | FTP | other *** search
/ Computer Music 2004 January / Computer Music Magazine 68 2004.iso / pc / Software / MAC Software / Full Software / Free Effects Mac / Smartelectronix - Bram / Madshifta OS9x OSX / source / dfx-library / dfxgui.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  24.2 KB  |  948 lines

  1. #ifndef __dfxgui
  2. #include "dfxgui.h"
  3. #endif
  4.  
  5. #include <stdio.h>
  6. #include <math.h>
  7.  
  8. // this is all for the internet stuff
  9. #if MAC
  10.     #ifndef __InternetConfig
  11.     #include <InternetConfig.h>
  12.     #endif
  13.     #ifndef __Gestalt
  14.     #include <Gestalt.h>
  15.     #endif
  16.     #ifndef __CodeFragments
  17.     #include <CodeFragments.h>
  18.     #endif
  19. #endif
  20. #if WIN32
  21.     #ifndef __shlobj
  22.     #include <shlobj.h>
  23.     #endif
  24.     #ifndef __shellapi
  25.     #include <shellapi.h>
  26.     #endif
  27. #endif
  28.  
  29.  
  30. //-----------------------------------------------------------------------------
  31. // Chunky Horizontal Slider
  32. //-----------------------------------------------------------------------------
  33. CHorizontalSliderChunky::CHorizontalSliderChunky(const CRect &size,
  34.                           CControlListener *listener,
  35.                           long     tag,          // child window identifier (tag)
  36.                           long     iMinXpos,    // min X position in pixel
  37.                           long     iMaxXpos,    // max X position in pixel
  38.                           long     numSteps,    // the number of value positions (chunky)
  39.                           CBitmap  *handle,     // bitmap of slider
  40.                           CBitmap  *background, // bitmap of background
  41.                           CPoint   &offset,     // offset in the background
  42.                           long     style)       // style (kLeft, kRight)
  43. :    CHorizontalSlider(size, listener, tag, iMinXpos, iMaxXpos, handle, background, offset, style), 
  44.     numSteps(numSteps), iMinXpos(iMinXpos), iMaxXpos(iMaxXpos)
  45. {
  46.     // it's all done in CHorizontalSlider()
  47. }
  48.  
  49. //------------------------------------------------------------------------
  50. CHorizontalSliderChunky::~CHorizontalSliderChunky()
  51. {
  52.     // nud
  53. }
  54.  
  55. //------------------------------------------------------------------------
  56. void CHorizontalSliderChunky::draw(CDrawContext *pContext)
  57. {
  58.   float fValue, fChunkRange = (float)(numSteps - 1);
  59.  
  60.     
  61.     if (style & kLeft)
  62.         fValue = value;
  63.     else 
  64.         fValue = 1.f - value;
  65.  
  66.     // make the value chunky
  67.     fValue = floorf(fValue*fChunkRange) / fChunkRange;
  68.     
  69.     COffscreenContext *pOScreen = new COffscreenContext (pParent, widthControl, heightControl, kBlackCColor);
  70.   
  71.     // (re)draw background
  72.     CRect rect (0, 0, widthControl, heightControl);
  73.     if (pBackground)
  74.     {
  75.         if (bTransparencyEnabled)
  76.             pBackground->drawTransparent(pOScreen, rect, offset);
  77.         else
  78.             pBackground->draw(pOScreen, rect, offset);
  79.     }
  80.  
  81.     // calc new coords of slider
  82.     float   fEffRange = (float)(iMaxXpos - iMinXpos);
  83.     CRect   rectNew;
  84.  
  85.     rectNew.top    = offsetHandle.v;
  86.     rectNew.bottom = rectNew.top + heightOfSlider;    
  87.  
  88.     rectNew.left   = offsetHandle.h + (int)(fValue * fEffRange);
  89.     rectNew.left   = (rectNew.left < minTmp) ? minTmp : rectNew.left;
  90.  
  91.     rectNew.right  = rectNew.left + widthOfSlider;
  92.     rectNew.right  = (rectNew.right > maxTmp) ? maxTmp : rectNew.right;
  93.  
  94.     // draw slider at new position
  95.     if (pHandle)
  96.     {
  97.         if (bDrawTransparentEnabled)
  98.             pHandle->drawTransparent(pOScreen, rectNew);
  99.         else 
  100.             pHandle->draw(pOScreen, rectNew);
  101.     }
  102.  
  103.     pOScreen->copyFrom(pContext, size);
  104.     delete pOScreen;
  105.  
  106. //    actualXPos = rectNew.left + size.left;    // in VSTGUI 2.1, but pointless?
  107.  
  108.     setDirty(false);
  109. }
  110.  
  111.  
  112.  
  113. //-----------------------------------------------------------------------------
  114. // Chunky Vertical Slider
  115. //-----------------------------------------------------------------------------
  116. CVerticalSliderChunky::CVerticalSliderChunky(const CRect &size,
  117.                           CControlListener *listener,
  118.                           long     tag,          // child window identifier (tag)
  119.                           long     iMinYpos,    // min Y position in pixel
  120.                           long     iMaxYpos,    // max Y position in pixel
  121.                           long     numSteps,    // the number of value positions (chunky)
  122.                           CBitmap  *handle,     // bitmap of slider
  123.                           CBitmap  *background, // bitmap of background
  124.                           CPoint   &offset,     // offset in the background
  125.                           long     style)       // style (kBottom, kTop)
  126. :    CVerticalSlider(size, listener, tag, iMinYpos, iMaxYpos, handle, background, offset, style), 
  127.     numSteps(numSteps), iMinYpos(iMinYpos), iMaxYpos(iMaxYpos)
  128. {
  129.     // it's all done in CVerticalSlider()
  130. }
  131.  
  132. //------------------------------------------------------------------------
  133. CVerticalSliderChunky::~CVerticalSliderChunky()
  134. {
  135.     // nud
  136. }
  137.  
  138. //------------------------------------------------------------------------
  139. void CVerticalSliderChunky::draw(CDrawContext *pContext)
  140.  
  141. {
  142.   float fValue, fChunkRange = (float)(numSteps - 1);
  143.  
  144.     
  145.     if (style & kTop)
  146.         fValue = value;
  147.     else 
  148.         fValue = 1.f - value;
  149.  
  150.     // make the value chunky
  151.     fValue = floorf(fValue*fChunkRange) / fChunkRange;
  152.     
  153.     COffscreenContext *pOScreen = new COffscreenContext (pParent, widthControl, heightControl, kBlackCColor);
  154.   
  155.     // (re)draw background
  156.     CRect rect (0, 0, widthControl, heightControl);
  157.     if (pBackground)
  158.     {
  159.         if (bTransparencyEnabled)
  160.             pBackground->drawTransparent(pOScreen, rect, offset);
  161.         else
  162.             pBackground->draw(pOScreen, rect, offset);
  163.     }
  164.     
  165.     // calc new coords of slider
  166.     float   fEffRange = (float)(iMaxYpos - iMinYpos);
  167.     CRect   rectNew;
  168.  
  169.     rectNew.left   = offsetHandle.h;
  170.     rectNew.right  = rectNew.left + widthOfSlider;    
  171.  
  172.     rectNew.top    = offsetHandle.v + (int)(fValue * fEffRange);
  173.     rectNew.top    = (rectNew.top < minTmp) ? minTmp : rectNew.top;
  174.  
  175.     rectNew.bottom = rectNew.top + heightOfSlider;
  176.     rectNew.bottom = (rectNew.bottom > maxTmp) ? maxTmp : rectNew.bottom;
  177.  
  178.     // draw slider at new position
  179.     if (pHandle)
  180.     {
  181.         if (bDrawTransparentEnabled)
  182.             pHandle->drawTransparent(pOScreen, rectNew);
  183.         else 
  184.             pHandle->draw(pOScreen, rectNew);
  185.     }
  186.  
  187.     pOScreen->copyFrom(pContext, size);
  188.     delete pOScreen;
  189.  
  190. //    actualYPos = rectNew.top + size.top;    // in VSTGUI 2.1, but pointless?
  191.  
  192.     setDirty(false);
  193. }
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. //------------------------------------------------------------------------
  201. // CHorizontalAnimSlider
  202. //------------------------------------------------------------------------
  203.  CHorizontalAnimSlider::CHorizontalAnimSlider(const CRect &size,
  204.                           CControlListener *listener,
  205.                           long     tag,            // child window identifier (tag)
  206.                           long     subPixmaps,    // number of subpixmaps
  207.                           long     heightOfOneImage, // pixel
  208.                           long     iMinXPos,    // min X position in pixel
  209.                           long     iMaxXPos,    // max X position in pixel
  210.                           CBitmap  *background,    // bitmap of background
  211.                           CPoint   &offset,        // offset in the background
  212.                           long     style)        // style (kLeft, kRight)
  213. :    CHorizontalSlider(size, listener, tag, iMinXPos, iMaxXPos, 0, background, offset, style), 
  214.     subPixmaps(subPixmaps), heightOfOneImage(heightOfOneImage)
  215. {
  216.     // nud
  217. }
  218.  
  219. //------------------------------------------------------------------------
  220. CHorizontalAnimSlider::~CHorizontalAnimSlider()
  221. {
  222.     // nud
  223. }
  224.  
  225. //------------------------------------------------------------------------
  226. void CHorizontalAnimSlider::draw(CDrawContext *pContext)
  227. {
  228.     CPoint where (offset.h, offset.v);
  229.  
  230.     if (value > 1.0f)
  231.         value = 1.0f;
  232.  
  233.      if (value > 0.0f)
  234.         where.v += heightOfOneImage * (int)(value * (float)(subPixmaps - 1) + 0.5f);
  235.  
  236.     if (pBackground)
  237.     {
  238.         if (bTransparencyEnabled)
  239.             pBackground->drawTransparent(pContext, size, where);
  240.         else
  241.             pBackground->draw(pContext, size, where);
  242.     }
  243.  
  244.     setDirty(false);
  245. }
  246.  
  247.  
  248.  
  249. //------------------------------------------------------------------------
  250. // CVerticalAnimSlider
  251. //------------------------------------------------------------------------
  252.  CVerticalAnimSlider::CVerticalAnimSlider(const CRect &size,
  253.                           CControlListener *listener,
  254.                           long     tag,            // child window identifier (tag)
  255.                           long     subPixmaps,    // number of subpixmaps
  256.                           long     heightOfOneImage, // pixel
  257.                           long     iMinYPos,    // min Y position in pixel
  258.                           long     iMaxYPos,    // max Y position in pixel
  259.                           CBitmap  *background,    // bitmap of background
  260.                           CPoint   &offset,        // offset in the background
  261.                           long     style)        // style (kBottom, kTop)
  262. :    CVerticalSlider(size, listener, tag, iMinYPos, iMaxYPos, 0, background, offset, style), 
  263.     subPixmaps(subPixmaps), heightOfOneImage(heightOfOneImage)
  264. {
  265.     // nud
  266. }
  267.  
  268. //------------------------------------------------------------------------
  269. CVerticalAnimSlider::~CVerticalAnimSlider()
  270. {
  271.     // nud
  272. }
  273.  
  274. //------------------------------------------------------------------------
  275. void CVerticalAnimSlider::draw(CDrawContext *pContext)
  276. {
  277.     CPoint where (offset.h, offset.v);
  278.  
  279.     if (value > 1.0f)
  280.         value = 1.0f;
  281.  
  282.      if (value > 0.0f)
  283.         where.v += heightOfOneImage * (int)(value * (float)(subPixmaps - 1) + 0.5f);
  284.  
  285.     if (pBackground)
  286.     {
  287.         if (bTransparencyEnabled)
  288.             pBackground->drawTransparent(pContext, size, where);
  289.         else
  290.             pBackground->draw(pContext, size, where);
  291.     }
  292.  
  293.     setDirty(false);
  294. }
  295.  
  296.  
  297.  
  298.  
  299.  
  300.  
  301. //------------------------------------------------------------------------
  302. // CNumberBox
  303. //------------------------------------------------------------------------
  304. CNumberBox::CNumberBox(const CRect &size, CControlListener *listener, long tag, 
  305.                             CBitmap *background, long textStyle, long controlStyle)
  306. :    CControl(size, listener, tag, background), 
  307.  horiTxtAlign(kCenterText), textStyle(textStyle), controlStyle(controlStyle), 
  308.  stringConvert(0), stringConvert2(0), string2FloatConvert(0), bTextTransparencyEnabled(true)
  309. {
  310.     offset (0, 0);
  311.  
  312.     fontID      = kNormalFont;
  313.     txtFace     = kNormalFace;
  314.     fontColor   = kWhiteCColor;
  315.     backColor   = kBlackCColor;
  316.     frameColor  = kBlackCColor;
  317.     shadowColor = kRedCColor;
  318.     userData    = 0;
  319.     if (textStyle & kNoDrawStyle)
  320.         setDirty(false);
  321.  
  322.     zoomFactor = 10.0f;
  323. }
  324.  
  325. //------------------------------------------------------------------------
  326. CNumberBox::~CNumberBox()
  327. {
  328.     // nud
  329. }
  330.  
  331. //------------------------------------------------------------------------
  332. void CNumberBox::setStyle(long val)
  333. {
  334.     if (textStyle != val)
  335.     {
  336.         textStyle = val;
  337.         setDirty();
  338.     }
  339. }
  340.  
  341. //------------------------------------------------------------------------
  342. void CNumberBox::draw(CDrawContext *pContext)
  343. {
  344.     char string[256];
  345.  
  346.     if (stringConvert2)
  347.     {
  348.         string[0] = 0;
  349.         stringConvert2(value, string, userData);
  350.     }
  351.     else if (stringConvert)
  352.     {
  353.         string[0] = 0;
  354.         stringConvert(value, string);
  355.     }
  356.     else
  357.         sprintf(string, "%2.2f", value);
  358.  
  359.     drawText(pContext, string);
  360. }
  361.  
  362. //------------------------------------------------------------------------
  363. void CNumberBox::drawText(CDrawContext *pContext, char *string, CBitmap *newBack)
  364. {
  365.     if (textStyle & kNoDrawStyle)
  366.     {
  367.         setDirty(false);
  368.         return;
  369.     }
  370.  
  371.     // draw the background
  372.     if (newBack)
  373.     {
  374.         if (bTransparencyEnabled)
  375.             newBack->drawTransparent(pContext, size, offset);
  376.         else
  377.             newBack->draw(pContext, size, offset);
  378.     }
  379.     else if (pBackground)
  380.     {
  381.         if (bTransparencyEnabled)
  382.             pBackground->drawTransparent(pContext, size, offset);
  383.         else
  384.             pBackground->draw(pContext, size, offset);
  385.     }
  386.     else
  387.     {
  388.         if (!bTransparencyEnabled)
  389.         {
  390.             pContext->setFillColor(backColor);
  391.             pContext->fillRect(size);
  392.  
  393.             if (!(textStyle & (k3DIn|k3DOut))) 
  394.             {
  395.                 pContext->setFrameColor(frameColor);
  396.                 pContext->drawRect(size);
  397.             }
  398.         }
  399.     }
  400.     // draw the frame for the 3D effect
  401.     if (textStyle & (k3DIn|k3DOut)) 
  402.     {
  403.         if (textStyle & k3DIn)
  404.             pContext->setFrameColor(backColor);
  405.         else
  406.             pContext->setFrameColor(frameColor);
  407.         CPoint p;
  408.         pContext->moveTo(p (size.left, size.bottom));
  409.         pContext->lineTo(p (size.left, size.top));
  410.         pContext->lineTo(p (size.right + 1, size.top));
  411.  
  412.         if (textStyle & k3DIn)
  413.             pContext->setFrameColor(frameColor);
  414.         else
  415.             pContext->setFrameColor(backColor);
  416.         pContext->moveTo(p (size.right, size.top + 1));
  417.         pContext->lineTo(p (size.right, size.bottom));
  418.         pContext->lineTo(p (size.left, size.bottom));
  419.     }
  420.  
  421.     if (!(textStyle & kNoTextStyle))
  422.     {
  423. //        pContext->setFont(fontID);                // v2.1
  424.         pContext->setFont(fontID, 0, txtFace);    // v2.2
  425.     
  426.         // draw darker text (as shadow)
  427.         if (textStyle & kShadowText) 
  428.         {
  429.             CRect newSize (size);
  430.             newSize.offset (1, 1);
  431.             pContext->setFontColor(shadowColor);
  432.             pContext->drawString(string, newSize, !bTextTransparencyEnabled, horiTxtAlign);
  433.         }
  434.         pContext->setFontColor(fontColor);
  435.         pContext->drawString(string, size, !bTextTransparencyEnabled, horiTxtAlign);
  436.     }
  437.  
  438.     setDirty(false);
  439. }
  440.  
  441. //------------------------------------------------------------------------
  442. void CNumberBox::mouse(CDrawContext *pContext, CPoint &where)
  443. {
  444.     if (!bMouseEnabled)
  445.         return;
  446.  
  447.     long button = pContext->getMouseButtons();
  448.     if (!(button & kLButton))
  449.         return;
  450.  
  451.     // set the default value
  452.     if (button == (kControl|kLButton))
  453.     {
  454.         value = getDefaultValue();
  455.         if (isDirty())
  456.             listener->valueChanged(pContext, this);
  457.         return;
  458.     }
  459.  
  460.     float old = oldValue;
  461.     CPoint firstPoint;
  462.     float fEntryState = value;
  463.     float middle = (vmax - vmin) / 2.f;
  464.     float range = 200.f;
  465.     long  oldButton = button;
  466.  
  467.     if (button & kShift)
  468.         range *= zoomFactor;
  469.     firstPoint = where;
  470.     float coef = (vmax - vmin) / range;
  471.  
  472.     CPoint oldWhere (-1, -1);
  473.  
  474.     // begin of edit parameter
  475.     getParent()->beginEdit(tag);
  476.     do
  477.     {
  478.         button = pContext->getMouseButtons();
  479.         if (where != oldWhere)
  480.         {
  481.             oldWhere = where;
  482.  
  483.             long diff = 0;
  484.             if (controlStyle & kHorizontal)
  485.                 diff += where.h - firstPoint.h;
  486.             if (controlStyle & kVertical)
  487.                 diff += firstPoint.v - where.v;
  488.             if (button != oldButton)
  489.             {
  490.                 range = 200.f;
  491.                 if (button & kShift)
  492.                     range *= zoomFactor;
  493.     
  494.                 float coef2 = (vmax - vmin) / range;
  495.                 fEntryState += diff * (coef - coef2);
  496.                 coef = coef2;
  497.                 oldButton = button;
  498.             }
  499.             value = fEntryState + (diff * coef);
  500.             bounceValue();
  501.  
  502.             if (isDirty())
  503.                 listener->valueChanged(pContext, this);
  504.         }
  505.  
  506.         pContext->getMouseLocation(where);
  507.         doIdleStuff();
  508.     } while (button & kLButton);
  509.  
  510.     // end of edit parameter
  511.     getParent()->endEdit(tag);
  512. }
  513.  
  514. //------------------------------------------------------------------------
  515. void CNumberBox::setFont(CFont fontID)
  516. {
  517.     // to force the redraw
  518.     if (this->fontID != fontID)
  519.         setDirty();
  520.     this->fontID = fontID;
  521. }
  522.  
  523. //------------------------------------------------------------------------
  524. void CNumberBox::setTxtFace(CTxtFace txtFace)
  525. {
  526.     // to force the redraw
  527.     if (this->txtFace != txtFace)
  528.         setDirty();
  529.     this->txtFace = txtFace;
  530. }
  531.  
  532. //------------------------------------------------------------------------
  533. void CNumberBox::setFontColor(CColor color)
  534. {
  535.     // to force the redraw
  536.     if (fontColor != color)
  537.         setDirty();
  538.     fontColor = color;
  539. }
  540.  
  541. //------------------------------------------------------------------------
  542. void CNumberBox::setBackColor(CColor color)
  543. {
  544.     // to force the redraw
  545.     if (backColor != color)
  546.         setDirty();
  547.     backColor = color;
  548. }
  549.  
  550. //------------------------------------------------------------------------
  551. void CNumberBox::setFrameColor(CColor color)
  552. {
  553.     // to force the redraw
  554.     if (frameColor != color)
  555.         setDirty();
  556.     frameColor = color;
  557. }
  558.  
  559. //------------------------------------------------------------------------
  560. void CNumberBox::setShadowColor(CColor color)
  561. {
  562.     // to force the redraw
  563.     if (shadowColor != color)
  564.         setDirty();
  565.     shadowColor = color;
  566. }
  567.  
  568. //------------------------------------------------------------------------
  569. void CNumberBox::setHoriAlign(CHoriTxtAlign hAlign)
  570. {
  571.     // to force the redraw
  572.     if (horiTxtAlign != hAlign)
  573.         setDirty();
  574.     horiTxtAlign = hAlign;
  575. }
  576.  
  577. //------------------------------------------------------------------------
  578. void CNumberBox::setBackOffset(CPoint &offset)
  579. {
  580.     this->offset = offset;
  581. }
  582.  
  583. //------------------------------------------------------------------------
  584. void CNumberBox::setStringConvert(void (*convert) (float value, char *string))
  585. {
  586.     stringConvert = convert;
  587. }
  588.  
  589. //------------------------------------------------------------------------
  590. void CNumberBox::setStringConvert(void (*convert) (float value, char *string,
  591.                                       void *userDta), void *userData)
  592. {
  593.     stringConvert2 = convert;
  594.     this->userData = userData;
  595. }
  596.  
  597. //------------------------------------------------------------------------
  598. void CNumberBox::setString2FloatConvert(void (*convert) (char *string, float &output))
  599. {
  600.     string2FloatConvert = convert;
  601. }
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608. //------------------------------------------------------------------------
  609. // CMultiToggle
  610. //------------------------------------------------------------------------
  611. CMultiToggle::CMultiToggle(const CRect &size, CControlListener *listener, long tag,
  612.                                  long subPixmaps,   // number of subPixmaps
  613.                                  long heightOfOneImage, // height of one image in pixel
  614.                                  CBitmap *background,
  615.                                  CPoint &offset)
  616. : CHorizontalSwitch(size, listener, tag, subPixmaps, heightOfOneImage, 
  617.                     subPixmaps, background, offset)
  618. {
  619.     // nud
  620. }
  621.  
  622. //------------------------------------------------------------------------
  623. CMultiToggle::~CMultiToggle()
  624. {
  625.     // nud
  626. }
  627.  
  628. //------------------------------------------------------------------------
  629. void CMultiToggle::mouse(CDrawContext *pContext, CPoint &where)
  630. {
  631.     if (!bMouseEnabled)
  632.         return;
  633.  
  634.     long button = pContext->getMouseButtons();
  635.     long direction;
  636. #if MAC
  637.     // rightclick or ctrl+leftclick
  638.     if ( (button & kRButton) || 
  639.          ((button & kLButton) && (button & kApple)) )
  640. #else
  641.     if (button & kRButton)    // right click reverses direction
  642. #endif
  643.         direction = -1;
  644.     else if (button & kLButton)
  645.         direction = 1;
  646.     else
  647.         return;
  648.     
  649.     // set the default value
  650.     if (button == (kControl|kLButton))
  651.     {
  652.         value = getDefaultValue();
  653.         if (isDirty())
  654.             listener->valueChanged(pContext, this);
  655.         return;
  656.     }
  657.     else
  658.     {
  659.         value = value + ((float)direction / (float)(subPixmaps-1));
  660.         if (value > 1.0f)
  661.             value = 0.0f;
  662.         else if (value < 0.0f)
  663.             value = 1.0f;
  664.  
  665.         if (isDirty())
  666.             listener->valueChanged (pContext, this);
  667.     }
  668. }
  669.  
  670.  
  671.  
  672.  
  673.  
  674.  
  675. //------------------------------------------------------------------------
  676. // CWebLink
  677. //------------------------------------------------------------------------
  678. CWebLink::CWebLink(const CRect &size, CControlListener *listener, long tag, 
  679.                             char *tempURL, CBitmap *background)
  680. :    CControl(size, listener, tag, background), tempURL(tempURL)
  681. {
  682.     URL = 0;
  683.     URL = new char[256];
  684.     if (tempURL && URL)
  685.         strcpy(URL, tempURL);
  686.  
  687.     mouseDown = false;
  688.     value = 0.0f;
  689.     error = 0;
  690. }
  691.  
  692. //------------------------------------------------------------------------
  693. CWebLink::~CWebLink()
  694. {
  695.     if (URL)
  696.         delete[] URL;
  697. }
  698.  
  699. //------------------------------------------------------------------------
  700. void CWebLink::draw(CDrawContext *pContext)
  701. {
  702.     if (pBackground)
  703.     {
  704.         long offsetY;
  705.         if (mouseDown)
  706.             offsetY = pBackground->getHeight() / 2;
  707.         else
  708.             offsetY = 0;
  709.  
  710.         if (bTransparencyEnabled)
  711.             pBackground->drawTransparent(pContext, size, CPoint(0, offsetY));
  712.         else
  713.             pBackground->draw(pContext, size, CPoint(0, offsetY));
  714.     }
  715.  
  716.     setDirty(false);
  717. }
  718.  
  719. //------------------------------------------------------------------------
  720. void CWebLink::mouse(CDrawContext *pContext, CPoint &where)
  721. {
  722.     mouseDown = true;
  723.  
  724.     if (!bMouseEnabled)
  725.     {
  726.         mouseDown = false;
  727.         return;
  728.     }
  729.  
  730.      long button = pContext->getMouseButtons();
  731.     if (!(button & kLButton))
  732.     {
  733.         mouseDown = false;
  734.         return;
  735.     }
  736.  
  737.     value = 1.0f;
  738.     draw(pContext);
  739.     openTheURL();
  740.     listener->valueChanged(pContext, this);
  741.  
  742.     do
  743.     {
  744.         button = pContext->getMouseButtons();
  745.         doIdleStuff();
  746.     } while (button & kLButton);
  747.  
  748.     mouseDown = false;
  749.     value = 0.0f;
  750.     draw(pContext);
  751.     listener->valueChanged(pContext, this);
  752. }
  753.  
  754. //------------------------------------------------------------------------
  755. void CWebLink::openTheURL()
  756. {
  757. #if MAC
  758.   ICInstance ICconnection;
  759.   long urlStart = 1, urlEnd, urlLength;
  760.     #if CALL_NOT_IN_CARBON
  761.     long gestaltResponse;
  762.     error = Gestalt('ICAp', &gestaltResponse);
  763.     if (error == noErr)
  764.     #endif
  765.         error = ICStart(&ICconnection, '????');
  766.     if ( (error == noErr) && (ICconnection == (void*)kUnresolvedCFragSymbolAddress) )
  767.         error = noErr + 3;
  768.     #if CALL_NOT_IN_CARBON
  769.     if (error == noErr)
  770.         error = ICFindConfigFile(ICconnection, 0, nil);
  771.     #endif
  772.     if (error == noErr)
  773.     {
  774.         // get this info for the ICLaunchURL function
  775.         urlEnd = urlLength = (long)strlen(URL) + urlStart;
  776.         if (urlLength > 255)
  777.             urlEnd = urlLength = 255;
  778.         // convert the URL string into a Pascal string for the ICLaunchURL function
  779.         char *pascalURL;
  780.         pascalURL = new char[256];
  781.         for (int i = 1; i < urlLength; i++)
  782.             pascalURL[i] = URL[i-1];    // move each char up one spot in the string array...
  783.         pascalURL[0] = (char)urlLength;    // ... & set the Pascal string length byte
  784.         //
  785.         error = ICLaunchURL(ICconnection, "\phttp", pascalURL, urlLength, &urlStart, &urlEnd);
  786.         delete[] pascalURL;
  787.     }
  788.     if (error == noErr)
  789.         error = ICStop(ICconnection);
  790. #endif
  791. #if WIN32
  792.     ShellExecute(NULL, "open", URL, NULL, NULL, SW_SHOWNORMAL);
  793. #endif
  794. }
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801. //-----------------------------------------------------------------------------
  802. // Fine Tune Button
  803. //-----------------------------------------------------------------------------
  804. CFineTuneButton::CFineTuneButton(const CRect &size, 
  805.                  CControlListener *listener, long tag,
  806.                                  long heightOfOneImage,
  807.                                  CBitmap *background,
  808.                                  CPoint &offset, 
  809.                                  long style)
  810. :    CKickButton(size, listener, tag, heightOfOneImage, background, offset), 
  811.     style(style)
  812. {
  813.     increment = 0.0001f;
  814.     if (style == kFineDown)
  815.         increment = -increment;
  816.  
  817.     value = 0.0f;
  818.     mouseDown = false;
  819. }
  820.  
  821. //------------------------------------------------------------------------
  822. CFineTuneButton::~CFineTuneButton()
  823. {
  824.     // nud
  825. }
  826.  
  827. //------------------------------------------------------------------------
  828. void CFineTuneButton::draw(CDrawContext *pContext)
  829. {
  830.     if (pBackground)
  831.     {
  832.         CPoint where (offset.h, offset.v);
  833.         if (mouseDown)
  834.             where.v += pBackground->getHeight() / 2;
  835.  
  836.         if (bTransparencyEnabled)
  837.             pBackground->drawTransparent(pContext, size, where);
  838.         else
  839.             pBackground->draw(pContext, size, where);
  840.     }
  841.  
  842.     setDirty(false);
  843. }
  844.  
  845. //------------------------------------------------------------------------
  846.  
  847. /* handle mouse events. Increment if clicked with the left mouse button,
  848.    increment * 10 if clicked with the right. (Right-click functionality
  849.    added by Tom 7) */
  850. void CFineTuneButton::mouse(CDrawContext *pContext, CPoint &where) {
  851.   mouseDown = true;
  852.  
  853.   if (!bMouseEnabled) {
  854.     mouseDown = false;
  855.     return;
  856.   }
  857.     
  858.   long button = pContext->getMouseButtons();
  859.   if (!(button & (kLButton | kRButton))) {
  860.     mouseDown = false;
  861.     return;
  862.   }
  863.  
  864. #if MAC
  865.   // rightclick or ctrl+leftclick for Mac
  866.   if ( (button & kRButton) || 
  867.        ((button & kLButton) && (button & kApple)) )
  868. #else
  869.   if (button & kRButton)
  870. #endif
  871.     value += (increment * 10.0f);
  872.   else if (button & kLButton)
  873.     value += increment;
  874.  
  875.   bounceValue();
  876.   listener->valueChanged(pContext, this);
  877.  
  878.   do {
  879.     if ( (where.h >= size.left && where.v >= size.top) &&
  880.      (where.h <= size.right && where.v <= size.bottom) )
  881.       mouseDown = true;
  882.     else
  883.       mouseDown = false;
  884.  
  885.     pContext->getMouseLocation(where);
  886.     button = pContext->getMouseButtons();
  887.     doIdleStuff();
  888.   } while (button & (kLButton | kRButton));
  889.  
  890.   mouseDown = false;
  891.   draw(pContext);
  892.   listener->valueChanged(pContext, this);
  893. }
  894.  
  895. //------------------------------------------------------------------------
  896. void CFineTuneButton::setIncrement(float newIncrement)
  897. {
  898.     increment = fabsf(newIncrement);
  899.     if (style == kFineDown)
  900.         increment = -increment;
  901. }
  902.  
  903. //------------------------------------------------------------------------
  904. void CFineTuneButton::setStyle(long newStyle)
  905. {
  906.     style = newStyle;
  907.     increment = fabsf(increment);
  908.     if (style == kFineDown)
  909.         increment = -increment;
  910. }
  911.  
  912.  
  913.  
  914.  
  915.  
  916.  
  917. //------------------------------------------------------------------------
  918. // CKickSpot
  919. //------------------------------------------------------------------------
  920. CKickSpot::CKickSpot(const CRect &size, CControlListener *listener, long tag, 
  921.                      CBitmap *background, CPoint &offset)
  922. :    CKickButton(size, listener, tag, size.bottom-size.top, background, offset)
  923. {
  924.     // nud
  925. }
  926.  
  927. //------------------------------------------------------------------------
  928. CKickSpot::~CKickSpot()
  929. {
  930.     // nud
  931. }
  932.  
  933. //------------------------------------------------------------------------
  934. void CKickSpot::draw(CDrawContext *pContext)
  935. {
  936.     CPoint where (offset.h, offset.v);
  937.  
  938.     if (pBackground)
  939.     {
  940.         if (bTransparencyEnabled)
  941.             pBackground->drawTransparent(pContext, size, where);
  942.         else
  943.             pBackground->draw(pContext, size, where);
  944.     }
  945.  
  946.     setDirty(false);
  947. }
  948.